/*
 * Sprite.cpp
 *
 *  Created on: Jul 27, 2009
 *      Author: kurt
 */

#include "Sprite.h"
#include "DrawingCanvas.h"
#include "ImageUtil.h"
#include "Types.h"
#include "GraphicsInstance.h"
#include <malloc.h>
#include <cstring>
#include <GL/gl.h>
#include <sstream>
#include <math.h>
#include <iostream>
using namespace std;
using namespace objdraw;

Sprite::~Sprite()
{
	if(auto_delete && image != NULL)
	{
		image->removeFromCanvas();
		image->Delete();
		image = NULL;
	}
}
Sprite::Sprite()
{
	start = Location(0,0);
	end = Location(0,0);
	color = Color(0,0,0);
	hidden = false;
	canvas = NULL;
	image = NULL;
	auto_delete = false;
	tileStart = tileStart = Location(0,0);
	frameWidth = frameHeight = 0.0f;
	frameStart = Location(0,0);
	currentFrame = 0;
	mirroredVert = mirroredHori = false;
}
Sprite::Sprite(Image * img, DrawingCanvas * c, bool auto_del)
{
	start = Location(0,0);
	end = Location(0,0);
	if(img != NULL)
		end = Location(img->getX() + img->getWidth(),img->getY() + img->getHeight());
	color = Color(0,0,0);
	hidden = false;
	canvas = c;
	image = img;
	auto_delete = auto_del;
	tileStart = Location(0,0);
	tileEnd = end;
	frameWidth = frameHeight = 0.0f;
	frameStart = Location(0,0);
	currentFrame = 0;
	mirroredVert = mirroredHori = false;
	if(canvas != NULL)
		canvas->getCanvasContent().addDrawable(this);
}
void Sprite::setTile(Location _start, Location _end)
{
	tileStart = _start;
	tileEnd = _end;
	setWidth(_end.x -_start.x);
	setHeight(_end.y - _start.y);
}
void Sprite::setFrameSize(Location _frameStart, float width, float height)
{
	frameStart = _frameStart;
	frameWidth = width;
	frameHeight = height;
	currentFrame = 0;
	setTile(frameStart,Location(frameStart.x + frameWidth, frameStart.y + frameHeight));
}
void Sprite::setFrame(uint frame)
{
//	Learned/copied/modified from oslib
	if(image == NULL) return;
	
	currentFrame = frame;
	uint framesPerLine = (((float)image->data.width) - frameStart.getX() ) / frameWidth;
	uint line = frame / framesPerLine;
	tileStart.setX((((float)(frame - line * framesPerLine)) * frameWidth) + frameStart.getX());
	tileStart.setY((line * frameHeight) + frameStart.getY());
	tileEnd.setX(tileStart.getX() + frameWidth);
	tileEnd.setY(tileStart.getY() + frameHeight);
}
void Sprite::setFrame(uint col, uint row)
{
	if(image == NULL) return;
	
	uint framesPerLine = (((float)image->data.width) - frameStart.getX() ) / frameWidth;
	setFrame((row * framesPerLine) + col);
}
uint Sprite::nextFrame()
{
	if(image == NULL) return 0;
	
	uint framesPerLine = (((float)image->data.width) - frameStart.getX() ) / frameWidth;
	uint framesPerCol = (((float)image->data.height) - frameStart.getY() ) / frameHeight;
	uint totalFrames = framesPerCol * framesPerLine;
	if(++currentFrame >= totalFrames)
		currentFrame = 0;
	setFrame(currentFrame);
	return currentFrame;
}
uint Sprite::prevFrame()
{
	if(image == NULL) return 0;
	
	if(--currentFrame < 0)
	{
		uint framesPerLine = (((float)image->data.width) - frameStart.getX() ) / frameWidth;
		uint framesPerCol = (((float)image->data.height) - frameStart.getY() ) / frameHeight;
		uint totalFrames = framesPerCol * framesPerLine;
		currentFrame = totalFrames-1;
	}
	setFrame(currentFrame);
	return currentFrame;
}
bool Sprite::isMirroredVert()
{
	return mirroredVert;
}
bool Sprite::isMirroredHori()
{
	return mirroredHori;
}
void Sprite::mirrorVert()
{
	mirroredVert = true;
}
void Sprite::mirrorHori()
{
	mirroredHori = true;
}
void Sprite::setVertMirror(bool mir)
{
	mirroredVert = mir;
}
void Sprite::setHoriMirror(bool mir)
{
	mirroredHori = mir;
}
void Sprite::render()
{
	if(image == NULL) return;
	if(hidden || image->getTexId() <= 0) 
		return;
	
	glEnable2D();
	glDisable(GL_DEPTH_TEST); 
	glEnable(GL_TEXTURE_2D);
	
//	flipTextureMatrix();
	
	glColor3f( 1.0f, 1.0f, 1.0f );
// setting the texture
	glBindTexture(GL_TEXTURE_2D,image->data.texid);
	glBegin(GL_QUADS);
			glTexCoord2f(!mirroredVert ? tileStart.x/image->data.textureWidth : tileEnd.x/image->data.textureWidth, !mirroredHori ? tileStart.y/image->data.textureHeight : tileEnd.y/image->data.textureHeight);
			glVertex2f(start.x, start.y);
			
			glTexCoord2f(!mirroredVert ? tileEnd.x/image->data.textureWidth : tileStart.x/image->data.textureWidth, !mirroredHori ? tileStart.y/image->data.textureHeight : tileEnd.y/image->data.textureHeight);
			glVertex2f(end.x, start.y);
			
			glTexCoord2f(!mirroredVert ? tileEnd.x/image->data.textureWidth : tileStart.x/image->data.textureWidth, !mirroredHori ? tileEnd.y/image->data.textureHeight : tileStart.y/image->data.textureHeight);
			glVertex2f(end.x, end.y);
			
			glTexCoord2f(!mirroredVert ? tileStart.x/image->data.textureWidth : tileEnd.x/image->data.textureWidth, !mirroredHori ? tileEnd.y/image->data.textureHeight : tileStart.y/image->data.textureHeight);
			glVertex2f(start.x, end.y);
	glEnd();
		
//	glBegin(GL_QUADS);
//		glTexCoord2f(!mirroredVert ? tileStart.x : tileEnd.x, !mirroredHori ? tileStart.y : tileEnd.y);
//		glVertex2f(start.x, start.y);
//		
//		glTexCoord2f(!mirroredVert ? tileEnd.x : tileStart.x, !mirroredHori ? tileStart.y : tileEnd.y);
//		glVertex2f(end.x, start.y);
//		
//		glTexCoord2f(!mirroredVert ? tileEnd.x : tileStart.x, !mirroredHori ? tileEnd.y : tileStart.y);
//		glVertex2f(end.x, end.y);
//		
//		glTexCoord2f(!mirroredVert ? tileStart.x : tileEnd.x, !mirroredHori ? tileEnd.y : tileStart.y);
//		glTexCoord2f(start.x, end.x);
//	glEnd();
	
//	glBegin(GL_QUADS);
//		glTexCoord2f(!mirroredVert ? 
//				tileStart.x/image->data.width : 
//				tileEnd.x/image->data.width, 
//				
//				!mirroredHori ? 
//				tileStart.y/image->data.height :
//				tileEnd.y/image->data.height);
//		glVertex2f(start.x, start.y);
//		
//		glTexCoord2f(!mirroredVert ? 
//				tileEnd.x/image->data.width : 
//				tileStart.x/image->data.width, 
//				
//				!mirroredHori ? 
//				tileStart.y/image->data.height : 
//				tileEnd.y/image->data.height);
//		glVertex2f(end.x, start.y);
//		
//		glTexCoord2f(!mirroredVert ? 
//				tileEnd.x/image->data.width : 
//				tileStart.x/image->data.width, 
//				
//				!mirroredHori ? 
//				tileEnd.y/image->data.height : 
//				tileStart.y/image->data.height);
//		glVertex2f(end.x, end.y);
//		
//		glTexCoord2f(!mirroredVert ? 
//				tileStart.x/image->data.width : 
//				tileEnd.x/image->data.width, 
//				
//				!mirroredHori ? 
//				tileEnd.y/image->data.height : 
//				tileStart.y/image->data.height);
//		glTexCoord2f(start.x, end.x);
//	glEnd();
	
// enable the depthtesting again.
	glEnable(GL_DEPTH_TEST); 
	glDisable(GL_TEXTURE_2D);
	glDisable2D();
}
